/*******************************************************************************
 *	                           oled spi.c
 *******************************************************************************/
#include "bsp.h"

#define OLED_SPI SPI1

/*****************************************************************************
 * @brief   hal init.
 *
 * @param   none
 *
 * @return  none
 *
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void bsp_spi_init(void)
{
	SPI_InitType SPI_InitStructure;
	intx_alloc();

	// 开启时钟
	intx_disable();
	RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_SPI1);
	intx_enable();

	// SPI 配置
	SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
	SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
	SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
	SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
	SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
	SPI_InitStructure.NSS = SPI_NSS_SOFT;
	SPI_InitStructure.FirstBit = SPI_FB_MSB;
	SPI_InitStructure.CRCPoly = 7;
	SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_128;

	SPI_Initializes(OLED_SPI, &SPI_InitStructure);
	// SPI_SS_Output_Enable(OLED_SPI);
	SPI_Set_Nss_Level(OLED_SPI, SPI_NSS_HIGH);
	SPI_ON(OLED_SPI);
}

/*****************************************************************************
 * @brief   cs ctr.
 *
 * @param   none
 *
 * @return  none
 *
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void bsp_spi_cs(uint8_t st)
{
}

/*****************************************************************************
 * @brief   spi speed.
 *****************************************************************************/
void bsp_spi_high_speed(void)
{
}

/*****************************************************************************
 * @brief   spi speed.
 *****************************************************************************/
void bsp_spi_low_speed(void)
{
}

/*****************************************************************************
 * @brief   spi delay.
 *****************************************************************************/
#define spi_read_delay() NOP4()
#define is_spi_rx_ready() (OLED_SPI->STS & SPI_STS_RNE)
#define spi_rx_reset()                        \
	while (is_spi_rx_ready())                 \
	{                                         \
		volatile uint32_t rd = OLED_SPI->DAT; \
	}
#define is_spi_busy() ((OLED_SPI->STS & SPI_STS_BUSY) != 0)
#define spi_send(dat) OLED_SPI->DAT = dat
#define is_spi_tx_full() ((OLED_SPI->STS & SPI_STS_TE) == 0)
#define is_spi_tx_empty() ((OLED_SPI->STS & SPI_STS_TE) != 0)
#define spi_read() OLED_SPI->DAT

/*****************************************************************************
 * @brief   spi data read.
 *****************************************************************************/
uint8_t bsp_spi_rb(void)
{
	spi_rx_reset();

	spi_send(0xFF);

	spi_read_delay();

	while (!is_spi_rx_ready())
		;

	return (spi_read());
}

void bsp_spi_wb(uint8_t dataW)
{
	volatile uint8_t rb;

	spi_rx_reset();

	spi_send(dataW);

	spi_read_delay();

	// while (!is_spi_rx_ready());
	while (is_spi_busy() || !is_spi_tx_empty())
		;

	rb = spi_read();
}

/*****************************************************************************
 * @brief   spi data write.
 *****************************************************************************/
uint8_t bsp_spi_write(const uint8_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		spi_send(*dataw++);
		spi_read_delay();
		while (is_spi_tx_full())
			;
	}

	spi_read_delay();

	while (is_spi_busy() || !is_spi_tx_empty())
		;

	spi_rx_reset();

	return (0);
}

/*****************************************************************************
 * @brief   spi data read.
 *****************************************************************************/
uint8_t bsp_spi_read(uint8_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset();

	while (Len--)
	{
		spi_send(0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready())
			;

		datar[rcnt++] = spi_read();
	}

	return 0;
}
